package com.artifact.mit.mypoint.service;

import static com.artifact.mit.mypoint.service.http.URIResources.LOGIN;
import static com.artifact.mit.mypoint.service.http.URIResources.POINT;
import static com.artifact.mit.mypoint.service.http.URIResources.POINT_SOURCE;
import static com.artifact.mit.mypoint.service.http.URIResources.PRODUCT_BY_CATEGORY;
import static com.artifact.mit.mypoint.service.http.URIResources.PROMO;
import static com.artifact.mit.mypoint.service.http.URIResources.NEWS;
import static com.artifact.mit.mypoint.service.util.Variable.PREFS_NAME;
import static com.artifact.mit.mypoint.service.util.Variable.SHARED_CTX;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;
import android.util.Log;

import com.artifact.mit.mypoint.service.http.MyPointHttpClient;
import com.artifact.mit.mypoint.service.model.api.News;
import com.artifact.mit.mypoint.service.model.api.Point;
import com.artifact.mit.mypoint.service.model.api.PointHistory;
import com.artifact.mit.mypoint.service.model.api.PointSource;
import com.artifact.mit.mypoint.service.model.api.ProductItem;
import com.artifact.mit.mypoint.service.model.api.Promo;
import com.artifact.mit.mypoint.service.model.api.User;

public class ServiceHandler implements MyPointServices {

	private ObjectMapper mapper = new ObjectMapper();
	private SharedPreferences preferences;
	private SharedPreferences.Editor editor;
	private MyPointHttpClient httpClient;
	
	private static final String CONTENT_TYPE = "Content-Type";
	private static final String RESULT = "application/json";
	private static final String AUTHORIZATION = "Authorization";
	private static final String TOKEN = "Token";

	public ServiceHandler(Context context) {
		httpClient = new MyPointHttpClient();
		preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
		editor = preferences.edit();
	}
	
	public void commitEditor(String shareKye, String value) {
		editor.putString(shareKye, value);
		editor.commit();
	}
		
	private String getToken() {
		return getB64(preferences.getString(SHARED_CTX, ""));
	}
		
	private String getB64Auth(String login, String pass) {
		String source = login + ":" + pass;
		String ret = "Basic " + getB64(source);
		return ret;
	}

	private String getB64(String source) {
		return Base64.encodeToString(source.getBytes(), Base64.URL_SAFE	| Base64.NO_WRAP);
	}
	
	private String convertBody(HttpEntity entity) throws Exception {
		return EntityUtils.toString(entity);
	}
	
	private Header[] defaultHeader(String token) {
		Header[] headers = { new BasicHeader(TOKEN, token), 
				new BasicHeader(CONTENT_TYPE, RESULT) };
		return headers;		
	}

	private Header[] authHeader(String token, String authKey) {
		Header[] headers = { new BasicHeader(TOKEN, token),
				new BasicHeader(CONTENT_TYPE, RESULT),
				new BasicHeader(AUTHORIZATION, authKey) };
		return headers;
	}
	
	@Override
	public User userService(String username, String password) throws Exception {
		String authKey = getB64Auth(username, password);
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("SerialNo", "1234567890"));
		String response = convertBody(httpClient.post(LOGIN, authHeader(getToken(), authKey), params).getEntity());
		User user = mapper.readValue(response, User.class);
		commitEditor(SHARED_CTX, user.getToken());
		return user;
	}

	@Override
	public Point pointService() throws Exception {
		String response = convertBody(httpClient.post(POINT, defaultHeader(getToken())).getEntity());
		Point point = mapper.readValue(response, Point.class);
		commitEditor(SHARED_CTX, point.getToken());
		return point;
	}

	@Override
	public PointSource pointSourceService() throws Exception {
		String response = convertBody(httpClient.get(POINT_SOURCE, defaultHeader(getToken())).getEntity());
		PointSource pointSource = mapper.readValue(response, PointSource.class);
		commitEditor(SHARED_CTX, pointSource.getToken());
		return pointSource;
	}

	@Override
	public PointHistory pointHistoryService() throws Exception {
		String response = convertBody(httpClient.get(POINT+"?date=&last=-1", defaultHeader(getToken())).getEntity());
		PointHistory pointHistory = mapper.readValue(response, PointHistory.class);
		Log.d("Point History Response", response);
		commitEditor(SHARED_CTX, pointHistory.getToken());
		return pointHistory;
	}
	
	@Override
	public Promo promoService() throws Exception {
		String response = convertBody(httpClient.get(PROMO, defaultHeader(getToken())).getEntity());
		Promo promo = mapper.readValue(response, Promo.class);
		commitEditor(SHARED_CTX, promo.getToken());
		return promo;
	}
		
	@Override
	public News newsService() throws Exception {
		String response = convertBody(httpClient.get(NEWS, defaultHeader(getToken())).getEntity());
		News news = mapper.readValue(response, News.class);
		commitEditor(SHARED_CTX, news.getToken());
		return news;
	}

	@Override
	public ProductItem productListByCatalogue(String catalogueId) throws Exception {
		String response = convertBody(httpClient.get(PRODUCT_BY_CATEGORY+"?catalogueID="+catalogueId, defaultHeader(getToken())).getEntity());
		System.err.println(response);
		ProductItem productItem = mapper.readValue(response, ProductItem.class);
		commitEditor(SHARED_CTX, productItem.getToken());
		return productItem;
	}
}